1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.awt.shell;
27
28 import java.awt.Image;
29 import java.awt.Toolkit;
30 import java.awt.image.BufferedImage;
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.*;
34 import java.util.concurrent.*;
35 import javax.swing.SwingConstants;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 final class Win32ShellFolder2 extends ShellFolder {
73
74 private static native void initIDs();
75
76 static {
77 initIDs();
78 }
79
80
81 public static final int DESKTOP = 0x0000;
82 public static final int INTERNET = 0x0001;
83 public static final int PROGRAMS = 0x0002;
84 public static final int CONTROLS = 0x0003;
85 public static final int PRINTERS = 0x0004;
86 public static final int PERSONAL = 0x0005;
87 public static final int FAVORITES = 0x0006;
88 public static final int STARTUP = 0x0007;
89 public static final int RECENT = 0x0008;
90 public static final int SENDTO = 0x0009;
91 public static final int BITBUCKET = 0x000a;
92 public static final int STARTMENU = 0x000b;
93 public static final int DESKTOPDIRECTORY = 0x0010;
94 public static final int DRIVES = 0x0011;
95 public static final int NETWORK = 0x0012;
96 public static final int NETHOOD = 0x0013;
97 public static final int FONTS = 0x0014;
98 public static final int TEMPLATES = 0x0015;
99 public static final int COMMON_STARTMENU = 0x0016;
100 public static final int COMMON_PROGRAMS = 0X0017;
101 public static final int COMMON_STARTUP = 0x0018;
102 public static final int COMMON_DESKTOPDIRECTORY = 0x0019;
103 public static final int APPDATA = 0x001a;
104 public static final int PRINTHOOD = 0x001b;
105 public static final int ALTSTARTUP = 0x001d;
106 public static final int COMMON_ALTSTARTUP = 0x001e;
107 public static final int COMMON_FAVORITES = 0x001f;
108 public static final int INTERNET_CACHE = 0x0020;
109 public static final int COOKIES = 0x0021;
110 public static final int HISTORY = 0x0022;
111
112
113 public static final int ATTRIB_CANCOPY = 0x00000001;
114 public static final int ATTRIB_CANMOVE = 0x00000002;
115 public static final int ATTRIB_CANLINK = 0x00000004;
116 public static final int ATTRIB_CANRENAME = 0x00000010;
117 public static final int ATTRIB_CANDELETE = 0x00000020;
118 public static final int ATTRIB_HASPROPSHEET = 0x00000040;
119 public static final int ATTRIB_DROPTARGET = 0x00000100;
120 public static final int ATTRIB_LINK = 0x00010000;
121 public static final int ATTRIB_SHARE = 0x00020000;
122 public static final int ATTRIB_READONLY = 0x00040000;
123 public static final int ATTRIB_GHOSTED = 0x00080000;
124 public static final int ATTRIB_HIDDEN = 0x00080000;
125 public static final int ATTRIB_FILESYSANCESTOR = 0x10000000;
126 public static final int ATTRIB_FOLDER = 0x20000000;
127 public static final int ATTRIB_FILESYSTEM = 0x40000000;
128 public static final int ATTRIB_HASSUBFOLDER = 0x80000000;
129 public static final int ATTRIB_VALIDATE = 0x01000000;
130 public static final int ATTRIB_REMOVABLE = 0x02000000;
131 public static final int ATTRIB_COMPRESSED = 0x04000000;
132 public static final int ATTRIB_BROWSABLE = 0x08000000;
133 public static final int ATTRIB_NONENUMERATED = 0x00100000;
134 public static final int ATTRIB_NEWCONTENT = 0x00200000;
135
136
137 public static final int SHGDN_NORMAL = 0;
138 public static final int SHGDN_INFOLDER = 1;
139 public static final int SHGDN_INCLUDE_NONFILESYS= 0x2000;
140 public static final int SHGDN_FORADDRESSBAR = 0x4000;
141 public static final int SHGDN_FORPARSING = 0x8000;
142
143
144 public enum SystemIcon {
145 IDI_APPLICATION(32512),
146 IDI_HAND(32513),
147 IDI_ERROR(32513),
148 IDI_QUESTION(32514),
149 IDI_EXCLAMATION(32515),
150 IDI_WARNING(32515),
151 IDI_ASTERISK(32516),
152 IDI_INFORMATION(32516),
153 IDI_WINLOGO(32517);
154
155 private final int iconID;
156
157 SystemIcon(int iconID) {
158 this.iconID = iconID;
159 }
160
161 public int getIconID() {
162 return iconID;
163 }
164 }
165
166 static class FolderDisposer implements sun.java2d.DisposerRecord {
167
168
169
170
171 long absolutePIDL;
172
173
174
175
176 long pIShellFolder;
177 long relativePIDL;
178
179 boolean disposed;
180 public void dispose() {
181 if (disposed) return;
182 invoke(new Callable<Void>() {
183 public Void call() {
184 if (relativePIDL != 0) {
185 releasePIDL(relativePIDL);
186 }
187 if (absolutePIDL != 0) {
188 releasePIDL(absolutePIDL);
189 }
190 if (pIShellFolder != 0) {
191 releaseIShellFolder(pIShellFolder);
192 }
193 return null;
194 }
195 });
196 disposed = true;
197 }
198 }
199 FolderDisposer disposer = new FolderDisposer();
200 private void setIShellFolder(long pIShellFolder) {
201 disposer.pIShellFolder = pIShellFolder;
202 }
203 private void setRelativePIDL(long relativePIDL) {
204 disposer.relativePIDL = relativePIDL;
205 }
206
207
208
209 private long pIShellIcon = -1L;
210 private String folderType = null;
211 private String displayName = null;
212 private Image smallIcon = null;
213 private Image largeIcon = null;
214 private Boolean isDir = null;
215
216
217
218
219 private boolean isPersonal;
220
221 private static String composePathForCsidl(int csidl) throws IOException, InterruptedException {
222 String path = getFileSystemPath(csidl);
223 return path == null
224 ? ("ShellFolder: 0x" + Integer.toHexString(csidl))
225 : path;
226 }
227
228
229
230
231
232 Win32ShellFolder2(final int csidl) throws IOException, InterruptedException {
233
234
235 super(null, composePathForCsidl(csidl));
236
237 invoke(new Callable<Void>() {
238 public Void call() throws InterruptedException {
239 if (csidl == DESKTOP) {
240 initDesktop();
241 } else {
242 initSpecial(getDesktop().getIShellFolder(), csidl);
243
244
245
246
247
248 long pIDL = disposer.relativePIDL;
249 parent = getDesktop();
250 while (pIDL != 0) {
251
252 long childPIDL = copyFirstPIDLEntry(pIDL);
253 if (childPIDL != 0) {
254
255
256 pIDL = getNextPIDLEntry(pIDL);
257 if (pIDL != 0) {
258
259
260
261 parent = new Win32ShellFolder2((Win32ShellFolder2) parent, childPIDL);
262 } else {
263
264
265 disposer.relativePIDL = childPIDL;
266 }
267 } else {
268 break;
269 }
270 }
271 }
272 return null;
273 }
274 }, InterruptedException.class);
275
276 sun.java2d.Disposer.addRecord(this, disposer);
277 }
278
279
280
281
282
283 Win32ShellFolder2(Win32ShellFolder2 parent, long pIShellFolder, long relativePIDL, String path) {
284 super(parent, (path != null) ? path : "ShellFolder: ");
285 this.disposer.pIShellFolder = pIShellFolder;
286 this.disposer.relativePIDL = relativePIDL;
287 sun.java2d.Disposer.addRecord(this, disposer);
288 }
289
290
291
292
293
294 Win32ShellFolder2(final Win32ShellFolder2 parent, final long relativePIDL) throws InterruptedException {
295 super(parent,
296 invoke(new Callable<String>() {
297 public String call() {
298 return getFileSystemPath(parent.getIShellFolder(), relativePIDL);
299 }
300 }, RuntimeException.class)
301 );
302 this.disposer.relativePIDL = relativePIDL;
303 sun.java2d.Disposer.addRecord(this, disposer);
304 }
305
306
307
308 private native void initDesktop();
309
310
311
312
313 private native void initSpecial(long desktopIShellFolder, int csidl);
314
315
316 public void setIsPersonal() {
317 isPersonal = true;
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331 protected Object writeReplace() throws java.io.ObjectStreamException {
332 return invoke(new Callable<File>() {
333 public File call() {
334 if (isFileSystem()) {
335 return new File(getPath());
336 } else {
337 Win32ShellFolder2 drives = Win32ShellFolderManager2.getDrives();
338 if (drives != null) {
339 File[] driveRoots = drives.listFiles();
340 if (driveRoots != null) {
341 for (int i = 0; i < driveRoots.length; i++) {
342 if (driveRoots[i] instanceof Win32ShellFolder2) {
343 Win32ShellFolder2 sf = (Win32ShellFolder2) driveRoots[i];
344 if (sf.isFileSystem() && !sf.hasAttribute(ATTRIB_REMOVABLE)) {
345 return new File(sf.getPath());
346 }
347 }
348 }
349 }
350 }
351
352 return new File("C:\\");
353 }
354 }
355 });
356 }
357
358
359
360
361
362 protected void dispose() {
363 disposer.dispose();
364 }
365
366
367
368
369
370
371
372 static native long getNextPIDLEntry(long pIDL);
373
374
375
376
377
378
379 static native long copyFirstPIDLEntry(long pIDL);
380
381
382 private static native long combinePIDLs(long ppIDL, long pIDL);
383
384
385
386 static native void releasePIDL(long pIDL);
387
388
389
390 private static native void releaseIShellFolder(long pIShellFolder);
391
392
393
394
395 private long getIShellFolder() {
396 if (disposer.pIShellFolder == 0) {
397 try {
398 disposer.pIShellFolder = invoke(new Callable<Long>() {
399 public Long call() {
400 assert(isDirectory());
401 assert(parent != null);
402 long parentIShellFolder = getParentIShellFolder();
403 if (parentIShellFolder == 0) {
404 throw new InternalError("Parent IShellFolder was null for "
405 + getAbsolutePath());
406 }
407
408
409
410 long pIShellFolder = bindToObject(parentIShellFolder,
411 disposer.relativePIDL);
412 if (pIShellFolder == 0) {
413 throw new InternalError("Unable to bind "
414 + getAbsolutePath() + " to parent");
415 }
416 return pIShellFolder;
417 }
418 }, RuntimeException.class);
419 } catch (InterruptedException e) {
420
421 }
422 }
423 return disposer.pIShellFolder;
424 }
425
426
427
428
429 public long getParentIShellFolder() {
430 Win32ShellFolder2 parent = (Win32ShellFolder2)getParentFile();
431 if (parent == null) {
432
433
434 return getIShellFolder();
435 }
436 return parent.getIShellFolder();
437 }
438
439
440
441
442 public long getRelativePIDL() {
443 if (disposer.relativePIDL == 0) {
444 throw new InternalError("Should always have a relative PIDL");
445 }
446 return disposer.relativePIDL;
447 }
448
449 private long getAbsolutePIDL() {
450 if (parent == null) {
451
452 return getRelativePIDL();
453 } else {
454 if (disposer.absolutePIDL == 0) {
455 disposer.absolutePIDL = combinePIDLs(((Win32ShellFolder2)parent).getAbsolutePIDL(), getRelativePIDL());
456 }
457
458 return disposer.absolutePIDL;
459 }
460 }
461
462
463
464
465 public Win32ShellFolder2 getDesktop() {
466 return Win32ShellFolderManager2.getDesktop();
467 }
468
469
470
471
472 public long getDesktopIShellFolder() {
473 return getDesktop().getIShellFolder();
474 }
475
476 private static boolean pathsEqual(String path1, String path2) {
477
478 return path1.equalsIgnoreCase(path2);
479 }
480
481
482
483
484 public boolean equals(Object o) {
485 if (o == null || !(o instanceof Win32ShellFolder2)) {
486
487 if (!(o instanceof File)) {
488 return super.equals(o);
489 }
490 return pathsEqual(getPath(), ((File) o).getPath());
491 }
492 Win32ShellFolder2 rhs = (Win32ShellFolder2) o;
493 if ((parent == null && rhs.parent != null) ||
494 (parent != null && rhs.parent == null)) {
495 return false;
496 }
497
498 if (isFileSystem() && rhs.isFileSystem()) {
499
500 return (pathsEqual(getPath(), rhs.getPath()) &&
501 (parent == rhs.parent || parent.equals(rhs.parent)));
502 }
503
504 if (parent == rhs.parent || parent.equals(rhs.parent)) {
505 try {
506 return pidlsEqual(getParentIShellFolder(), disposer.relativePIDL, rhs.disposer.relativePIDL);
507 } catch (InterruptedException e) {
508 return false;
509 }
510 }
511
512 return false;
513 }
514
515 private static boolean pidlsEqual(final long pIShellFolder, final long pidl1, final long pidl2)
516 throws InterruptedException {
517 return invoke(new Callable<Boolean>() {
518 public Boolean call() {
519 return compareIDs(pIShellFolder, pidl1, pidl2) == 0;
520 }
521 }, RuntimeException.class);
522 }
523
524
525 private static native int compareIDs(long pParentIShellFolder, long pidl1, long pidl2);
526
527 private volatile Boolean cachedIsFileSystem;
528
529
530
531
532 public boolean isFileSystem() {
533 if (cachedIsFileSystem == null) {
534 cachedIsFileSystem = hasAttribute(ATTRIB_FILESYSTEM);
535 }
536
537 return cachedIsFileSystem;
538 }
539
540
541
542
543 public boolean hasAttribute(final int attribute) {
544 Boolean result = invoke(new Callable<Boolean>() {
545 public Boolean call() {
546
547 return (getAttributes0(getParentIShellFolder(),
548 getRelativePIDL(), attribute)
549 & attribute) != 0;
550 }
551 });
552
553 return result != null && result;
554 }
555
556
557
558
559
560
561
562
563
564
565 private static native int getAttributes0(long pParentIShellFolder, long pIDL, int attrsMask);
566
567
568
569 private static String getFileSystemPath(final long parentIShellFolder, final long relativePIDL) {
570 int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER;
571 if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() &&
572 getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) {
573
574 String s =
575 getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(),
576 getLinkLocation(parentIShellFolder, relativePIDL, false));
577 if (s != null && s.startsWith("\\\\")) {
578 return s;
579 }
580 }
581 return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING);
582 }
583
584
585 static String getFileSystemPath(final int csidl) throws IOException, InterruptedException {
586 return invoke(new Callable<String>() {
587 public String call() throws IOException {
588 return getFileSystemPath0(csidl);
589 }
590 }, IOException.class);
591 }
592
593
594 private static native String getFileSystemPath0(int csidl) throws IOException;
595
596
597
598 private static boolean isNetworkRoot(String path) {
599 return (path.equals("\\\\") || path.equals("\\") || path.equals("//") || path.equals("/"));
600 }
601
602
603
604
605
606 public File getParentFile() {
607 return parent;
608 }
609
610 public boolean isDirectory() {
611 if (isDir == null) {
612
613
614 if (hasAttribute(ATTRIB_FOLDER) && !hasAttribute(ATTRIB_BROWSABLE)) {
615 isDir = Boolean.TRUE;
616 } else if (isLink()) {
617 ShellFolder linkLocation = getLinkLocation(false);
618 isDir = Boolean.valueOf(linkLocation != null && linkLocation.isDirectory());
619 } else {
620 isDir = Boolean.FALSE;
621 }
622 }
623 return isDir.booleanValue();
624 }
625
626
627
628
629
630
631 private long getEnumObjects(final boolean includeHiddenFiles) throws InterruptedException {
632 return invoke(new Callable<Long>() {
633 public Long call() {
634 boolean isDesktop = disposer.pIShellFolder == getDesktopIShellFolder();
635
636 return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles);
637 }
638 }, RuntimeException.class);
639 }
640
641
642
643
644 private native long getEnumObjects(long pIShellFolder, boolean isDesktop,
645 boolean includeHiddenFiles);
646
647
648
649
650 private native long getNextChild(long pEnumObjects);
651
652
653 private native void releaseEnumObjects(long pEnumObjects);
654
655
656
657
658
659 private static native long bindToObject(long parentIShellFolder, long pIDL);
660
661
662
663
664
665
666 public File[] listFiles(final boolean includeHiddenFiles) {
667 SecurityManager security = System.getSecurityManager();
668 if (security != null) {
669 security.checkRead(getPath());
670 }
671
672 try {
673 return invoke(new Callable<File[]>() {
674 public File[] call() throws InterruptedException {
675 if (!isDirectory()) {
676 return null;
677 }
678
679
680
681 if (isLink() && !hasAttribute(ATTRIB_FOLDER)) {
682 return new File[0];
683 }
684
685 Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop();
686 Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal();
687
688
689
690
691 long pIShellFolder = getIShellFolder();
692
693 ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
694 long pEnumObjects = getEnumObjects(includeHiddenFiles);
695 if (pEnumObjects != 0) {
696 try {
697 long childPIDL;
698 int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
699 do {
700 childPIDL = getNextChild(pEnumObjects);
701 boolean releasePIDL = true;
702 if (childPIDL != 0 &&
703 (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
704 Win32ShellFolder2 childFolder;
705 if (Win32ShellFolder2.this.equals(desktop)
706 && personal != null
707 && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
708 childFolder = personal;
709 } else {
710 childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL);
711 releasePIDL = false;
712 }
713 list.add(childFolder);
714 }
715 if (releasePIDL) {
716 releasePIDL(childPIDL);
717 }
718 } while (childPIDL != 0 && !Thread.currentThread().isInterrupted());
719 } finally {
720 releaseEnumObjects(pEnumObjects);
721 }
722 }
723 return Thread.currentThread().isInterrupted()
724 ? new File[0]
725 : list.toArray(new ShellFolder[list.size()]);
726 }
727 }, InterruptedException.class);
728 } catch (InterruptedException e) {
729 return new File[0];
730 }
731 }
732
733
734
735
736
737
738
739 Win32ShellFolder2 getChildByPath(final String filePath) throws InterruptedException {
740 return invoke(new Callable<Win32ShellFolder2>() {
741 public Win32ShellFolder2 call() throws InterruptedException {
742 long pIShellFolder = getIShellFolder();
743 long pEnumObjects = getEnumObjects(true);
744 Win32ShellFolder2 child = null;
745 long childPIDL;
746
747 while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
748 if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
749 String path = getFileSystemPath(pIShellFolder, childPIDL);
750 if (path != null && path.equalsIgnoreCase(filePath)) {
751 long childIShellFolder = bindToObject(pIShellFolder, childPIDL);
752 child = new Win32ShellFolder2(Win32ShellFolder2.this,
753 childIShellFolder, childPIDL, path);
754 break;
755 }
756 }
757 releasePIDL(childPIDL);
758 }
759 releaseEnumObjects(pEnumObjects);
760 return child;
761 }
762 }, InterruptedException.class);
763 }
764
765 private volatile Boolean cachedIsLink;
766
767
768
769
770 public boolean isLink() {
771 if (cachedIsLink == null) {
772 cachedIsLink = hasAttribute(ATTRIB_LINK);
773 }
774
775 return cachedIsLink;
776 }
777
778
779
780
781 public boolean isHidden() {
782 return hasAttribute(ATTRIB_HIDDEN);
783 }
784
785
786
787
788 private static native long getLinkLocation(long parentIShellFolder,
789 long relativePIDL, boolean resolve);
790
791
792
793
794
795 public ShellFolder getLinkLocation() {
796 return getLinkLocation(true);
797 }
798
799 private ShellFolder getLinkLocation(final boolean resolve) {
800 return invoke(new Callable<ShellFolder>() {
801 public ShellFolder call() {
802 if (!isLink()) {
803 return null;
804 }
805
806 ShellFolder location = null;
807 long linkLocationPIDL = getLinkLocation(getParentIShellFolder(),
808 getRelativePIDL(), resolve);
809 if (linkLocationPIDL != 0) {
810 try {
811 location =
812 Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(),
813 linkLocationPIDL);
814 } catch (InterruptedException e) {
815
816 } catch (InternalError e) {
817
818
819 }
820 }
821 return location;
822 }
823 });
824 }
825
826
827 long parseDisplayName(final String name) throws IOException, InterruptedException {
828 return invoke(new Callable<Long>() {
829 public Long call() throws IOException {
830 return parseDisplayName0(getIShellFolder(), name);
831 }
832 }, IOException.class);
833 }
834
835
836 private static native long parseDisplayName0(long pIShellFolder, String name) throws IOException;
837
838
839
840 private static native String getDisplayNameOf(long parentIShellFolder,
841 long relativePIDL,
842 int attrs);
843
844
845
846
847 public String getDisplayName() {
848 if (displayName == null) {
849 displayName =
850 invoke(new Callable<String>() {
851 public String call() {
852 return getDisplayNameOf(getParentIShellFolder(),
853 getRelativePIDL(), SHGDN_NORMAL);
854 }
855 });
856 }
857 return displayName;
858 }
859
860
861
862 private static native String getFolderType(long pIDL);
863
864
865
866
867 public String getFolderType() {
868 if (folderType == null) {
869 final long absolutePIDL = getAbsolutePIDL();
870 folderType =
871 invoke(new Callable<String>() {
872 public String call() {
873 return getFolderType(absolutePIDL);
874 }
875 });
876 }
877 return folderType;
878 }
879
880
881 private native String getExecutableType(String path);
882
883
884
885
886 public String getExecutableType() {
887 if (!isFileSystem()) {
888 return null;
889 }
890 return getExecutableType(getAbsolutePath());
891 }
892
893
894
895
896
897 private static Map smallSystemImages = new HashMap();
898 private static Map largeSystemImages = new HashMap();
899 private static Map smallLinkedSystemImages = new HashMap();
900 private static Map largeLinkedSystemImages = new HashMap();
901
902
903 private static native long getIShellIcon(long pIShellFolder);
904
905
906 private static native int getIconIndex(long parentIShellIcon, long relativePIDL);
907
908
909 private static native long getIcon(String absolutePath, boolean getLargeIcon);
910
911
912 private static native long extractIcon(long parentIShellFolder, long relativePIDL,
913 boolean getLargeIcon);
914
915
916 private static native long getSystemIcon(int iconID);
917 private static native long getIconResource(String libName, int iconID,
918 int cxDesired, int cyDesired,
919 boolean useVGAColors);
920
921
922
923
924 private static native int[] getIconBits(long hIcon, int iconSize);
925
926 private static native void disposeIcon(long hIcon);
927
928 static native int[] getStandardViewButton0(int iconIndex);
929
930
931 private long getIShellIcon() {
932 if (pIShellIcon == -1L) {
933 pIShellIcon = getIShellIcon(getIShellFolder());
934 }
935
936 return pIShellIcon;
937 }
938
939 private static Image makeIcon(long hIcon, boolean getLargeIcon) {
940 if (hIcon != 0L && hIcon != -1L) {
941
942 int size = getLargeIcon ? 32 : 16;
943 int[] iconBits = getIconBits(hIcon, size);
944 if (iconBits != null) {
945 BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
946 img.setRGB(0, 0, size, size, iconBits, 0, size);
947 return img;
948 }
949 }
950 return null;
951 }
952
953
954
955
956
957 public Image getIcon(final boolean getLargeIcon) {
958 Image icon = getLargeIcon ? largeIcon : smallIcon;
959 if (icon == null) {
960 icon =
961 invoke(new Callable<Image>() {
962 public Image call() {
963 Image newIcon = null;
964 if (isFileSystem()) {
965 long parentIShellIcon = (parent != null)
966 ? ((Win32ShellFolder2) parent).getIShellIcon()
967 : 0L;
968 long relativePIDL = getRelativePIDL();
969
970
971 int index = getIconIndex(parentIShellIcon, relativePIDL);
972 if (index > 0) {
973 Map imageCache;
974 if (isLink()) {
975 imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages;
976 } else {
977 imageCache = getLargeIcon ? largeSystemImages : smallSystemImages;
978 }
979 newIcon = (Image) imageCache.get(Integer.valueOf(index));
980 if (newIcon == null) {
981 long hIcon = getIcon(getAbsolutePath(), getLargeIcon);
982 newIcon = makeIcon(hIcon, getLargeIcon);
983 disposeIcon(hIcon);
984 if (newIcon != null) {
985 imageCache.put(Integer.valueOf(index), newIcon);
986 }
987 }
988 }
989 }
990
991 if (newIcon == null) {
992
993 long hIcon = extractIcon(getParentIShellFolder(),
994 getRelativePIDL(), getLargeIcon);
995 newIcon = makeIcon(hIcon, getLargeIcon);
996 disposeIcon(hIcon);
997 }
998
999 if (newIcon == null) {
1000 newIcon = Win32ShellFolder2.super.getIcon(getLargeIcon);
1001 }
1002 return newIcon;
1003 }
1004 });
1005 if (getLargeIcon) {
1006 largeIcon = icon;
1007 } else {
1008 smallIcon = icon;
1009 }
1010 }
1011 return icon;
1012 }
1013
1014
1015
1016
1017 static Image getSystemIcon(SystemIcon iconType) {
1018 long hIcon = getSystemIcon(iconType.getIconID());
1019 Image icon = makeIcon(hIcon, true);
1020 disposeIcon(hIcon);
1021 return icon;
1022 }
1023
1024
1025
1026
1027 static Image getShell32Icon(int iconID, boolean getLargeIcon) {
1028 boolean useVGAColors = true;
1029
1030 int size = getLargeIcon ? 32 : 16;
1031
1032 Toolkit toolkit = Toolkit.getDefaultToolkit();
1033 String shellIconBPP = (String)toolkit.getDesktopProperty("win.icon.shellIconBPP");
1034 if (shellIconBPP != null) {
1035 useVGAColors = shellIconBPP.equals("4");
1036 }
1037
1038 long hIcon = getIconResource("shell32.dll", iconID, size, size, useVGAColors);
1039 if (hIcon != 0) {
1040 Image icon = makeIcon(hIcon, getLargeIcon);
1041 disposeIcon(hIcon);
1042 return icon;
1043 }
1044 return null;
1045 }
1046
1047
1048
1049
1050
1051
1052
1053 public File getCanonicalFile() throws IOException {
1054 return this;
1055 }
1056
1057
1058
1059
1060 public boolean isSpecial() {
1061 return isPersonal || !isFileSystem() || (this == getDesktop());
1062 }
1063
1064
1065
1066
1067
1068
1069 public int compareTo(File file2) {
1070 if (!(file2 instanceof Win32ShellFolder2)) {
1071 if (isFileSystem() && !isSpecial()) {
1072 return super.compareTo(file2);
1073 } else {
1074 return -1;
1075 }
1076 }
1077 return Win32ShellFolderManager2.compareShellFolders(this, (Win32ShellFolder2) file2);
1078 }
1079
1080
1081 private static final int LVCFMT_LEFT = 0;
1082 private static final int LVCFMT_RIGHT = 1;
1083 private static final int LVCFMT_CENTER = 2;
1084
1085 public ShellFolderColumnInfo[] getFolderColumns() {
1086 return invoke(new Callable<ShellFolderColumnInfo[]>() {
1087 public ShellFolderColumnInfo[] call() {
1088 ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder());
1089
1090 if (columns != null) {
1091 List<ShellFolderColumnInfo> notNullColumns =
1092 new ArrayList<ShellFolderColumnInfo>();
1093 for (int i = 0; i < columns.length; i++) {
1094 ShellFolderColumnInfo column = columns[i];
1095 if (column != null) {
1096 column.setAlignment(column.getAlignment() == LVCFMT_RIGHT
1097 ? SwingConstants.RIGHT
1098 : column.getAlignment() == LVCFMT_CENTER
1099 ? SwingConstants.CENTER
1100 : SwingConstants.LEADING);
1101
1102 column.setComparator(new ColumnComparator(getIShellFolder(), i));
1103
1104 notNullColumns.add(column);
1105 }
1106 }
1107 columns = new ShellFolderColumnInfo[notNullColumns.size()];
1108 notNullColumns.toArray(columns);
1109 }
1110 return columns;
1111 }
1112 });
1113 }
1114
1115 public Object getFolderColumnValue(final int column) {
1116 return invoke(new Callable<Object>() {
1117 public Object call() {
1118 return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column);
1119 }
1120 });
1121 }
1122
1123
1124 private native ShellFolderColumnInfo[] doGetColumnInfo(long iShellFolder2);
1125
1126
1127 private native Object doGetColumnValue(long parentIShellFolder2, long childPIDL, int columnIdx);
1128
1129
1130 private static native int compareIDsByColumn(long pParentIShellFolder, long pidl1, long pidl2, int columnIdx);
1131
1132
1133 public void sortChildren(final List<? extends File> files) {
1134
1135
1136 invoke(new Callable<Void>() {
1137 public Void call() {
1138 Collections.sort(files, new ColumnComparator(getIShellFolder(), 0));
1139
1140 return null;
1141 }
1142 });
1143 }
1144
1145 private static class ColumnComparator implements Comparator<File> {
1146 private final long parentIShellFolder;
1147
1148 private final int columnIdx;
1149
1150 public ColumnComparator(long parentIShellFolder, int columnIdx) {
1151 this.parentIShellFolder = parentIShellFolder;
1152 this.columnIdx = columnIdx;
1153 }
1154
1155
1156 public int compare(final File o, final File o1) {
1157 Integer result = invoke(new Callable<Integer>() {
1158 public Integer call() {
1159 if (o instanceof Win32ShellFolder2
1160 && o1 instanceof Win32ShellFolder2) {
1161
1162 return compareIDsByColumn(parentIShellFolder,
1163 ((Win32ShellFolder2) o).getRelativePIDL(),
1164 ((Win32ShellFolder2) o1).getRelativePIDL(),
1165 columnIdx);
1166 }
1167 return 0;
1168 }
1169 });
1170
1171 return result == null ? 0 : result;
1172 }
1173 }
1174 }